using Gateway.IRepositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ShardingCore;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using System.Reflection;

namespace Gateway.EFCore;

/// <summary>
/// ef 扩展
/// </summary>
public static class EFCoreExtension
{
    /// <summary>
    /// 注入ef
    /// </summary>
    /// <param name="services"></param>
    /// <param name="configuration"></param>
    /// <param name="migrationAssembly"></param>
    public static void AddEF(this IServiceCollection services, IConfiguration configuration, string migrationAssembly)
    {
        // services.AddDbContext<CoreDbContext>(options =>
        // {
        //     options.UseMySql(configuration["ConnectionSetting"],
        //         ServerVersion.AutoDetect(configuration["ConnectionSetting"]),
        //         sql => sql.MigrationsAssembly(migrationAssembly));
        // });

        // services.AddShardingConfigure<ShareCoreDbContext>().UseRouteConfig(op =>
        // {
        //     op.ScanVirtualTableRoute(migrationAssembly);
        //     // op.AddShardingTableRoute<OrderVirtualTableRoute>();
        // });
        //添加分片配置
        services.AddShardingDbContext<ShareCoreDbContext>()
            .UseRouteConfig(op => { op.ScanVirtualTableRoute(); }).UseConfig((sp, op) =>
            {
                op.UseShardingQuery((conn, builder) =>
                {
                    builder.UseMySql(conn, ServerVersion.AutoDetect(conn),
                        sql => sql.MigrationsAssembly(migrationAssembly));
                });
                op.UseShardingTransaction((conn, builder) =>
                {
                    builder.UseMySql(conn, ServerVersion.AutoDetect(conn.ConnectionString),
                        sql => sql.MigrationsAssembly(migrationAssembly));
                });
                op.AddDefaultDataSource(Guid.NewGuid().ToString("n"),
                    configuration["ConnectionSetting"]);
            }).AddShardingCore();


        services.AddScoped(typeof(IAppRepository<>), typeof(EFRepository<>));
        services.AddScoped<IUnitOfWork, UnitOfWork>();

        //services.AddScoped(provider =>
        //    provider.GetRequiredService<ShareCoreDbContext>().Database.Migrate()
        //);
    }


    private static void ScanVirtualTableRoute(this IShardingRouteConfigOptions options)
    {
        //var assemblies = AppDomain.CurrentDomain.GetAssemblies();
        //var assembly = assemblies.FirstOrDefault(x => x.FullName!.Contains(typeof(EFCoreExtension).Namespace!));
        //if (assembly == null)
        //{
        //    throw new ArgumentNullException("未找到程序集：" + typeof(EFCoreExtension).FullName);
        //}
        var assembly = Assembly.Load("Gateway.Domain");
        var list = assembly.GetTypes().Where(x =>
            IsIndirectlyGenericType(x.BaseType!, typeof(AbstractShardingOperatorVirtualTableRoute<,>))).ToList();

        if (list.Count > 0)
        {
            foreach (Type type in list)
            {
                options.AddShardingTableRoute(type);
            }
        }
    }


    private static bool IsIndirectlyGenericType(Type type, Type genericType)
    {
        while (type != null && type.IsGenericType)
        {
            if (type.GetGenericTypeDefinition() == genericType)
            {
                return true;
            }

            type = type.BaseType!;
        }

        return false;
    }
}